/**
 * @team Ka10psia 
 * 1. Itai Bashan
 * 2. Gil Blasbalg
 * 3. Nadav Harnik
 */

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import pars.AST;
import pars.LibAst;
import ic.ast.Node;
import pars.OurParser;
import ic.ast.PrettyPrint;
import ic.ast.decl.Program;
import interpeter.Interpeter;
//import ast.Expr;
import lex.Lexer;
import lex.Token;
import Symbol.*;


public class Main
{
	

        public static void main(String[] args) throws IOException
        {
                Lexer lex = new Lexer();
                OurParser parser = new OurParser();
                List<Token> tokens = new LinkedList<Token>();
                boolean b=false;
                Scope GlobalScope=new Scope("Global", ScopeType.Global, null);// QAQA check "Global"
        		//Scope.setGlobalScope(GlobalScope);
                try {
                        
                        /*If library-file is provided - proccess libfile*/
                        if(args.length>=2 && args[1].startsWith("-L")){
                                
                                //Extract library filename
                                String libFileName = new String();
                               // libFileName = args[1].substring(2);
                                libFileName = args[1];    //QAQA to cahnge back to the line above after qa                       
                                Lexer libraryLex = new Lexer();
                                OurParser libraryParser = new OurParser();
                                List<Token> libraryTokens = new LinkedList<Token>();
                                
                            	//GlobalScope=new Symbol.GlobalScope();
                        		
                        		
                        		
                                // create token list
                                lex.process(libFileName, libraryTokens);
                                //Create a parsing tree
                                fun.parser.Tree libastTree = parser.process(libraryTokens, true);
                                if(libastTree != null){
                                        //Create an AST parsing tree
                                        ic.ast.Node astLib = LibAst.constructAstLib(libastTree);
                                        if(astLib!=null){
                                                //System.out.println((astLib).accept(new ic.ast.PrettyPrint()));
                                                astLib.setScope(GlobalScope);
                                                astLib.accept(new SymbolTable());
                                               // Scope g=SymbolTable.getGlobalScope();
                                               b=true;
                                               // System.out.println("\n");//qaqa
                                               // g.printSymbolTable();
                                        }

                                }else{
                                        //Something went wrong with libastTree construction - exit program
                                        return;
                                }
                        }
                        
                        /*Proccess program file*/
                        
                        // create token list
                        lex.process(args[0], tokens);
                        //Create a parsing tree
                        fun.parser.Tree astTree = parser.process(tokens, false);
                        if(astTree!=null){
                                //Create an AST parsing tree            
                                Node ast=AST.constructAst(astTree);
                                if(ast!=null){
                                      // System.out.println((ast).accept(new PrettyPrint()));
                                	if (args.length>=2 && !(args[1].startsWith("-L"))){	//execute interpeter	
                    
                                		Program p = (Program) ast;
                                		Interpeter interpeter = new Interpeter(p);
                                		Object ob = interpeter.interpetMethod(args);
                                		interpeter.printObject(ob);
                                	
                                	}else{	//continue to compilation, symbol table
 
                                		ast.setScope(GlobalScope);
                                        ast.accept(new SymbolTable());
                                        b=true;
                                       // System.out.println("\n*****GIL GIL GIL ***************************\n"); /*Gil*/
                                       b = (boolean) ast.accept(new TypeSafety(GlobalScope)); /*Gil*/
                                       
                                	}   	
                                }
                        }else{
                                //Something went wrong with libastTree construction - exit program
                                return;
                        }                        
                        if(b){
                        	// System.out.println("\n");//qaqa
                           	 GlobalScope.printSymbolTable();
                        }
                }
                catch (Exception e) {
                        System.err.println(e);
                }
        }
}